/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "napi_led_controller_client.h"
#include "Client.h"

#include <pthread.h>
#include <unistd.h>

#include "hilog_wrapper.h"

#define MAX_BUFFER_SIZE 128

BearSocketMgr* bearSocketMgr;


void NAPI_Bear_Controller_Client_Init(napi_env env, napi_value exports)
{
    HILOG_INFO("[NAPI Bear Controller] NAPI_Bear_Controller_Client_Init calBear.");
    napi_property_descriptor desc[] = {
        DECLARE_NAPI_FUNCTION("Connect", NAPI_Connect),
        DECLARE_NAPI_FUNCTION("Send", NAPI_Send),
        DECLARE_NAPI_FUNCTION("Close", NAPI_Close)
    };

    napi_value result = nullptr;
    napi_define_class(env,
        "Bear_Controller",
        NAPI_AUTO_LENGTH,
        NAPI_Bear_Controller_Client_Constructor,
        nullptr,
        sizeof(desc) / sizeof(*desc),
        desc,
        &result);
    napi_set_named_property(env, exports, "Bear_Controller", result);
    NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
}

/*
 * Constructor
 */
napi_value NAPI_Bear_Controller_Client_Constructor(napi_env env, napi_callback_info info)
{
    HILOG_INFO("[NAPI Bear Controller] NAPI_Bear_Controller_Client_Constructor calBear.");
    size_t argc = 0;
    napi_value argv = nullptr;
    napi_value thisArg = nullptr;
    void *data = nullptr;
    napi_get_cb_info(env, info, &argc, &argv, &thisArg, &data);
    napi_value global = 0;
    napi_get_global(env, &global);
    return thisArg;
}


// void MyConnect(){
//     BearSocketMgr->Start();
//     // napi_value result;
//     // napi_value napi_connectionStatus;
//     // if (BearSocketMgr->GetConnectionStatus()) {
//     //     int32_t connectionStatus = 1;
//     //     NAPI_CALL(env, napi_create_object(env, &result));
//     //     NAPI_CALL(env, napi_set_named_property(env, result, "connection_status", napi_connectionStatus));
//     // }else{
//     //     int32_t connectionStatus = 0;
//     //     NAPI_CALL(env, napi_create_object(env, &result));
//     //     NAPI_CALL(env, napi_set_named_property(env, result, "connection_status", napi_connectionStatus));
//     // }
//     napi_value result;
//     napi_create_int32(env, 1, &result);
//     HILOG_INFO("NAPI process defered");
//     //回调
//     napi_resolve_deferred(
//         env,
//         result
//     );
//     napi_delete_async_work(
//         env,
//     );
//     HILOG_INFO("NAPI_ finish");
// }

void connectCarExe(napi_env env, void* argv){
    HILOG_INFO("Bear_NAPI_connectCarExe");
    //NAPI执行
    HILOG_INFO("NAPI exe part");
    //AsyncCallbackInfo_connectCar* callback_info = (AsyncCallbackInfo_connectCar*)argv;
    //写入数据
    // HILOG_INFO("NAPI_connectCarExe try to get mem CAR_CONNECT_KEY %d size = %d\n", CAR_CONNECT_KEY, SHM_SIZE);
    // SharedMemory writer(CAR_CONNECT_KEY, SHM_SIZE);
    // Connect_Info tmp_connect_info = *(Connect_Info*)writer.getMemory(sizeof(Connect_Info));
    // strcpy(tmp_connect_info.ip, callback_info->ip);
    // // tmp_connect_info.ip = callback_info->ip;
    // tmp_connect_info.port = callback_info->port;
    // tmp_connect_info.type = callback_info->type;
    // writer.setMemory(&tmp_connect_info, sizeof(Connect_Info));
    bearSocketMgr->Start();
    HILOG_INFO("Bear_NAPI_connectCarExe finish");

}


void connectCarCom(napi_env env, napi_status status, void* argv){
    HILOG_INFO("Bear_NAPI_connectCarCom");
    AsyncCallbackInfo_connectCar* callback_info = (AsyncCallbackInfo_connectCar*)argv;
    HILOG_INFO("NAPI set value");
    // int32_t connectionStatus = 0;
    // //转化为napi_value
    // napi_value napi_connectionStatus;
    // NAPI_CALL(env, napi_create_int32(env, connectionStatus, &napi_connectionStatus));
    napi_value result;
    // NAPI_CALL(env, napi_create_object(env, &results));
    // NAPI_CALL(env, napi_set_named_property(env, results, "connection_status", napi_connectionStatus));
    napi_create_int32(env, 1, &result);
    HILOG_INFO("NAPI process defered");
    //回调
    napi_resolve_deferred(
        env,
        callback_info->deferred,
        result
    );

    napi_delete_async_work(
        env,
        callback_info->asyncWork
    );
    HILOG_INFO("Bear_NAPI_connectCarExe finish");

    delete callback_info;

}


napi_value NAPI_Connect(napi_env env, napi_callback_info info){
    HILOG_INFO("[NAPI Bear Controller] NAPI_Connect calBear");
    //获取napi参数到argv
    size_t argc = 1;
    napi_value argv[argc];
    NAPI_CALL(env,napi_get_cb_info(env,info, &argc, argv, NULL, NULL));
    HILOG_INFO("[NAPI Car Controller] NAPI_Connect JS args get");
    bearSocketMgr = new BearSocketMgr();  //【确保不会离开函数作用域不会被自动回收】
    HILOG_INFO("[NAPI Bear Controller] NAPI_Connect CarSocketMgr init");
     // 创建一个工作
     AsyncCallbackInfo_connectCar* callback_info = (AsyncCallbackInfo_connectCar*)argv;
    napi_value work_name;
     napi_status status;//返回状态
    status = napi_create_string_utf8(
        env,
        "connectLed",
        NAPI_AUTO_LENGTH,
        &work_name
    );
    // 创建一个工作
    status = napi_create_async_work(
        env,
        NULL,
        work_name,
        connectCarExe,
        connectCarCom,
        callback_info,
        &(callback_info->asyncWork)
    );

    // 放入队列
    status = napi_queue_async_work(
        env,
        callback_info->asyncWork
    );
    //BearSocketMgr->Start();
    HILOG_INFO("[NAPI Bear Controller] NAPI_Connect CarSocketMgr.Connect() calBear");
    //if (BearSocketMgr->GetConnectionStatus()) {
        HILOG_INFO("[NAPI Bear Controller] Connection success");
        //需要传递给js的值
        int32_t connectionStatus = 0;
        //转化为napi_value
        napi_value napi_connectionStatus;
        NAPI_CALL(env, napi_create_int32(env, connectionStatus, &napi_connectionStatus));
        //构建object
        napi_value results;
        NAPI_CALL(env, napi_create_object(env, &results));
        NAPI_CALL(env, napi_set_named_property(env, results, "connection_status", napi_connectionStatus));
        //构建Promise回调
        napi_value promise;
        napi_deferred deferred;
        NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
        NAPI_CALL(env, napi_resolve_deferred(env, deferred, results));
        deferred = NULL;
        return promise;
    //}
    // else{
    //     HILOG_INFO("[NAPI Bear Controller] Connection fail");
    //     //运行析构函数
    //     BearSocketMgr->~BearSocketMgr();
    //     //需要传递给js的值
    //     int32_t connectionStatus = 0;
    //     //转化为napi_value
    //     napi_value napi_connectionStatus;
    //     NAPI_CALL(env, napi_create_int32(env, connectionStatus, &napi_connectionStatus));
    //     //构建object
    //     napi_value results;
    //     NAPI_CALL(env, napi_create_object(env, &results));
    //     NAPI_CALL(env, napi_set_named_property(env, results, "connection_status", napi_connectionStatus));
    //     //构建Promise回调
    //     napi_value promise;
    //     napi_deferred deferred;
    //     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
    //     NAPI_CALL(env, napi_resolve_deferred(env, deferred, results));
    //     deferred = NULL;
    //     return promise;
    // }

};
napi_value NAPI_Send(napi_env env, napi_callback_info info){
    HILOG_INFO("[NAPI Bear Controller] NAPI_Send calBear");
    size_t argc = 1;
    napi_value argv[argc];
    NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
    napi_value napi_data;
    NAPI_CALL(env, napi_get_named_property(env, argv[0], "data", &napi_data));
    char data[MAX_BUFFER_SIZE];
    size_t len = MAX_BUFFER_SIZE;
    NAPI_CALL(env, napi_get_value_string_utf8(env, napi_data, data, MAX_BUFFER_SIZE, &len));
    HILOG_INFO("[NAPI Car Controller] NAPI_Send C++ args get, data is %s", data);
    bearSocketMgr->Send(data);
    if (bearSocketMgr->GetSendStatus() == -1) {
        HILOG_INFO("[NAPI Car Controller] Send fail");
        int32_t sendStatus = -1;
        napi_value napi_sendStatus;
        NAPI_CALL(env, napi_create_int32(env, sendStatus, &napi_sendStatus));
        napi_value results;
        NAPI_CALL(env, napi_create_object(env, &results));
        NAPI_CALL(env, napi_set_named_property(env, results, "send_status", napi_sendStatus));
        napi_value promise;
        napi_deferred deferred;
        NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
        NAPI_CALL(env, napi_resolve_deferred(env, deferred, results));
        deferred = NULL;
        return promise;
    }
    else{
        HILOG_INFO("[NAPI Bear Controller] Send success");
        int32_t sendStatus = 1;
        napi_value napi_sendStatus;
        NAPI_CALL(env, napi_create_int32(env, sendStatus, &napi_sendStatus));
        napi_value results;
        NAPI_CALL(env, napi_create_object(env, &results));
        NAPI_CALL(env, napi_set_named_property(env, results, "send_status", napi_sendStatus));
        napi_value promise;
        napi_deferred deferred;
        NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
        NAPI_CALL(env, napi_resolve_deferred(env, deferred, results));
        deferred = NULL;
        return promise;
    }
    
}

napi_value NAPI_Close(napi_env env, napi_callback_info info){
    HILOG_INFO("[NAPI Bear Controller] NAPI_Close CalBear");
    bearSocketMgr->Close();
    if (bearSocketMgr != NULL){
        delete(bearSocketMgr);
        bearSocketMgr=NULL;
        
    }
    napi_value napi_closeStatus;
    if (bearSocketMgr == NULL){
        HILOG_INFO("[NAPI Bear Controller] Close success");
        int32_t closeStatus = 1;
        NAPI_CALL(env, napi_create_int32(env, closeStatus, &napi_closeStatus));

    }
    else{
        HILOG_INFO("[NAPI Bear Controller] Close fail");
        int32_t closeStatus = -1;
        NAPI_CALL(env, napi_create_int32(env, closeStatus, &napi_closeStatus));
    }
    napi_value results;
    NAPI_CALL(env, napi_create_object(env, &results));
    NAPI_CALL(env, napi_set_named_property(env, results, "close_status", napi_closeStatus));
    napi_value promise;
    napi_deferred deferred;
    NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
    NAPI_CALL(env, napi_resolve_deferred(env, deferred, results));
    deferred = NULL;
    return promise;
}


